package com.bdk.middle.common.util;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;

/**
 * 日期工具类
 * @author yanweiqi
 * @since 2016-5-6
 *
 */
public class LocalDateUtils {
     
    private static ZoneId zone = ZoneId.systemDefault();
    
	/**
	 * yyyy-MM-dd HH:mm:ss
	 */
	public static final String DATE_FORMAT_LONG = "yyyy-MM-dd HH:mm:ss";
	
	public static final String DATE_FORMAT_LONG1 = "yyyy/MM/dd HH:mm:ss";

	/**
	 * yyyy-MM-dd HHmmss
	 */
	public static final String DATE_FORMAT_LONG_NOCOMMA = "yyyy-MM-dd HHmmss";
	/**
	 * yyyy-MM-dd HHmmss.S
	 */
	public static final String DATE_FORMAT_LONG_NOCOMMAS = "yyyy-MM-dd HHmmss.SSS";

	/**
	 * yyyy-MM-dd HH:mm
	 */
	public static final String DATE_FORMAT_MIDDLE = "yyyy-MM-dd HH:mm";
	/**
	 * yyyy-MM-dd HHmm
	 */
	public static final String DATE_FORMAT_MIDDLE_NOCOMMA = "yyyy-MM-dd HHmm";

	/**
	 * yyyy-MM-dd
	 */
	public static final String DATE_FORMAT_SHORT = "yyyy-MM-dd";

	/**
	 * yyyyMMdd
	 */
	public static final String DATE_FORMAT_SHORT2 = "yyyyMMdd";

	/**
	 * yyyy/MM/dd
	 */
	public static final String DATE_FORMAT_SHORT3 = "yyyy/MM/dd";

	/**
	 * yyyy.MM.dd
	 */
	public static final String DATE_FORMAT_SHORT4 = "yyyy.MM.dd";

	/**
	 * ddMMMyy
	 */
	public static final String DATE_FORMAT_SHORT5 = "ddMMMyy";

	/**
	 * yyyyMMddHHmmss
	 */
	public static final String DATE_FORMAT_SHORT6 = "yyyyMMddHHmmss";
	

	/**
	 * ddMMM
	 */
	public static final String DATE_FORMAT_SHORT7 = "ddMMM";

	/**
	 * yyMMdd
	 */
	public static final String DATE_FORMAT_SHORT8 = "yyMMdd";
	
	/**
	 * yyyyMMddHHmmssSSS
	 */
	public static final String DATE_FORMAT_SHORT9 = "yyyyMMddHHmmssSSS";
	
	/**
	 * 获取自由格式的当前时间
	 * @param timeFormat  格式
	 * @return
	 */
	public static String getTodayByFormat(String timeFormat){
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(timeFormat));
    }
     
    /**
     * 字符串转Date
     * @param date
     * @return
     * @throws Exception
     */
    public static Date convertToDate(String date) throws Exception{
        LocalDate localDate = null;
        if(null == date){
            throw new NullPointerException("date isn't null");
        } else {
            localDate = LocalDate.parse(date);
            return convertToDate(localDate);
        }
    }
     
    /**
     * 字符串转LocalDateTime
     * @param date
     * @return localDateTime
     */
    public static LocalDateTime convertToLocalDateTime(String date){
        LocalDateTime localDateTime = null;
        if(null == date){
            throw new NullPointerException("date isn't null");
        } else {
            localDateTime = LocalDateTime.parse(date);
            return localDateTime;
        }
    }
     
    /**
     * LocalDate转Date
     * @param localDate
     * @return Date
     */
    public static Date convertToDate(LocalDate localDate){
        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
        return Date.from(instant);
    }
     
    /**
     * LocalDate转Date
     * @param localDateTime
     * @return Date
     */
    public static Date convertToDate(LocalDateTime localDateTime){
        Instant instant = localDateTime.atZone(zone).toInstant();
        return Date.from(instant);
    }
     
    /**
     * Date转LocalDate
     * @param date
     * @return localDate
     */
    public static LocalDate convertToLocalDate(Date date){
        Instant instant = date.toInstant();
        return convertToLocalDateTime(instant).toLocalDate();
    }
         
    /**
     * Date转LocalTime
     * @param date
     * @return localDate
     */
    public static LocalTime convertToLocalTime(Date date){
        Instant instant = date.toInstant();
        return convertToLocalDateTime(instant).toLocalTime();
    }
     
    /**
     * Date转LocalDatetime
     * @param date
     * @return localDate
     */
    public static LocalDateTime convertToLocalDateTime(Date date){
        Instant instant = date.toInstant();
        return convertToLocalDateTime(instant);
    }
     
 
    /**
     * Instant转LocalDateTime
     * @param instant
     * @return
     */
    public static LocalDateTime convertToLocalDateTime(Instant instant){
        return LocalDateTime.ofInstant(instant, zone);
    }
    
    /**
     * 	将timestamp转为LocalDateTime
     * @param timestamp
     * @return
     */
    public static LocalDateTime timestamToDatetime(long timestamp){
        Instant instant = Instant.ofEpochMilli(timestamp);
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }
     
    /**
     * LocalDateTime转Instant
     * @param localDateTime
     * @return
     */
    public static Instant convertToInstant(LocalDateTime localDateTime){
        return localDateTime.atZone(zone).toInstant();
    }
     
    /**
     * LocalDate转Instant
     * @param localDate
     * @return
     */
    public static Instant convertToInstant(LocalDate localDate){
        return localDate.atStartOfDay(zone).toInstant();
    }
     
    /**
     * LocalDate转LocalDateTime
     * @param localDate
     * @return LocalDateTime
     */
    public static LocalDateTime convertToLocalDateTime(LocalDate localDate){
        return localDate.atStartOfDay();
    }
     
    /**
     * 日周期格式化
     * @param localDateTime
     * @param formatStyle
     * @return
     */
    public static String formatter(LocalDateTime localDateTime, String formatStyle){
        return DateTimeFormatter.ofPattern(formatStyle).format(localDateTime);
    }
     
    /**
     * 设置年
     * @param sourceDate
     * @param year
     * @return LocalDateTime
     */
    public static LocalDateTime setYear(LocalDateTime sourceDate, Integer year){
        return sourceDate.withYear(year);
    }
     
    /**
     * 设置月
     * @param sourceDate
     * @param month
     * @return LocalDateTime
     */
    public static LocalDateTime setMonth(LocalDateTime sourceDate, Integer month){
        return sourceDate.withMonth(month);
    }
     
    /**
     * 设置天
     * @param sourceDate
     * @param dayOfMonth
     * @return LocalDateTime
     */
    public static LocalDateTime setDayOfMonth(LocalDateTime sourceDate, Integer dayOfMonth){
        return sourceDate.withDayOfMonth(dayOfMonth);
    }
     
    /**
     * 设置小时
     * @param sourceDate
     * @param hour
     * @return
     */
    public static LocalDateTime setHour(LocalDateTime sourceDate,Integer hour){
        return sourceDate.withHour(hour);
         
    }
     
    /**
     * 设置分钟
     * @param sourceDate
     * @param minute
     * @return
     */
    public static LocalDateTime setMinute(LocalDateTime sourceDate,Integer minute){
        return sourceDate.withMinute(minute);
    }
     
    /**
     * 设置秒
     * @param sourceDate
     * @param second
     * @return
     */
    public static LocalDateTime setSecond(LocalDateTime sourceDate,Integer second){
        return sourceDate.withSecond(second);
    }
     
    /**
     * 修改年月日
     * @param sourceDate
     * @param year
     * @param month
     * @param dayOfMonth
     * @return
     */
    public static LocalDateTime setYMD(LocalDateTime sourceDate, Integer year, Integer month, Integer dayOfMonth) {
        return sourceDate.withYear(year).withMonth(month).withDayOfMonth(dayOfMonth);
    }
     
    /**
     * 修改时分秒
     * @param sourceDate
     * @param hour
     * @param minute
     * @param second
     * @return
     */
    public static LocalDateTime setHMS(LocalDateTime sourceDate,Integer hour, Integer minute, Integer second) {
        return sourceDate.withHour(hour).withMinute(minute).withSecond(second);
    }
     
    /**
     * 计算相差的天数
     * @param beginDate
     * @param endDate
     * @return
     */
    public static int getInteverDays(LocalDate beginDate,LocalDate endDate){
        Period period = Period.between(beginDate, endDate);
        return period.getDays();
    }
    
    //获取指定日期的毫秒
    public static Long getMilliByTime(LocalDateTime time) {
        return time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    //获取指定日期的秒
    public static Long getSecondsByTime(LocalDateTime time) {
        return time.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
    }
     
    /**
     * 日期加减
     * @param  num  数量
     * @param  unit  单位
     * @param  localDate 原日期
     * @return LocalDate 增加后的日期
     */
    @SuppressWarnings("static-access")
    public static LocalDate addLocalDate(long num,ChronoUnit unit,final LocalDate localDate){
        LocalDate resultDate;
        if(num > 0){
            resultDate = localDate.now().plus(num, unit);
        } else {
            resultDate = localDate.now().minus(Math.abs(num), unit);
        }
        return resultDate;
    }
     
    /**
     * 日期时分秒加
     * @param  num  数量
     * @param  unit 单位
     * @param  localDateTime 原日期
     * @return LocalDateTime 增加后的日期
     */
    @SuppressWarnings("static-access")
    public static LocalDateTime addLocalDateTime(long num,ChronoUnit unit,LocalDateTime localDateTime){
        LocalDateTime resultDateTime;
        if(num > 0){
            resultDateTime = localDateTime.now().plus(num, unit);
        } else {
            resultDateTime = localDateTime.now().minus(Math.abs(num),unit);
        }
        return resultDateTime;
    }
     
    /**
     * 时分秒加减
     * @param  num  数量
     * @param  unit 单位
     * @param  localTime 原日期
     * @return LocalDateTime 增加后的日期
     */
    @SuppressWarnings("static-access")
    public static LocalTime addLocalTime(long num,ChronoUnit unit,LocalTime localTime){
        LocalTime resultTime;
        if(num > 0){
            resultTime = localTime.now().plus(num, unit);
        } else {
            resultTime = localTime.now().minus(Math.abs(num), unit);
        }
        return resultTime;
    }
    
    /**
     * 获取两个日期的差  field参数为ChronoUnit.*
     * @param startTime
     * @param endTime
     * @param field  单位(年月日时分秒)
     * @return
     */
    public static long betweenTwoTime(LocalDateTime startTime, LocalDateTime endTime, ChronoUnit field) {
        Period period = Period.between(LocalDate.from(startTime), LocalDate.from(endTime));
        if (field == ChronoUnit.YEARS) return period.getYears();
        if (field == ChronoUnit.MONTHS) return period.getYears() * 12 + period.getMonths();
        return field.between(startTime, endTime);
    }
    
    /*
     * 毫秒转化时分秒毫秒
     */
    public static String formatTime(Long ms) {
        Integer ss = 1000;
        Integer mi = ss * 60;
        Integer hh = mi * 60;
        Integer dd = hh * 24;
 
        Long day = ms / dd;
        Long hour = (ms - day * dd) / hh;
        Long minute = (ms - day * dd - hour * hh) / mi;
        Long second = (ms - day * dd - hour * hh - minute * mi) / ss;
        Long milliSecond = ms - day * dd - hour * hh - minute * mi - second * ss;
        
        StringBuffer sb = new StringBuffer();
        if(day > 0) {
            sb.append(day+"天");
        }
        if(hour > 0) {
            sb.append(hour+"小时");
        }
        if(minute > 0) {
            sb.append(minute+"分钟");
        }
        if(second > 0) {
            sb.append(second+"秒");
        }
        if(milliSecond > 0) {
            sb.append(milliSecond+"毫秒");
        }
        return sb.toString();
    }
    
    /**
     * 	从0开始判断oldTime与today是不是想差整年如果是则返回true
     * @param oldTime
     * @param today
     * @param index
     * @return
     */
    public static boolean judgeFewYears(LocalDate oldTime, LocalDate today,int index) {
    	if(oldTime.equals(today)) {
    		return true;
    	} else {
    		//一年或几年后的日期
    		LocalDate nextYear = today.plus(index,ChronoUnit.YEARS);
    		//判断几年后的日期是不是在今天之后
    		if(nextYear.isAfter(today)) {
    			return false;
    		} else {
    			index++;
    			return judgeFewYears(oldTime.plus(index,ChronoUnit.YEARS),today,index);
    		}
    	}
    }

}